<?php


namespace App\Task;


use App\Game\Conf\MainCmd;
use App\Game\Conf\SubCmd;
use App\Game\Core\Packet;

class GangCardTask
{

    /**
     * 用户打牌逻辑处理
     * @param $user_room_data
     * @param $out_cards
     * @param $account
     * @param $fd
     * @throws \Exception
     */
    public function doGang($user_room_data, $out_cards, $account, $fd): void
    {
        $game_conf = config('game');
        $user_conf = config('user');
        $card = $out_cards['card'];
        $serv = server();
        $flag = true;
        $user_data = json_decode($user_room_data[$account], true);
        $my_card = $user_data['card'];
        $countValuesArr = array_count_values($my_card);
        if (!isset($countValuesArr[$card])) {
            $msg = array('status' => 1, 'info' => '杠牌非法，手牌数据有问题');
            $flag = $this->gameGangCard($serv, $fd, $msg);
        }
        if ($countValuesArr[$card] != 3) {
            $msg = array('status' => 2, 'info' => '杠牌非法，手牌数据有问题');
            $flag = $this->gameGangCard($serv, $fd, $msg);
        }
        $gangArr = isset($my_card['gang']) ? $my_card['gang'] : [];
        if (in_array($card, $gangArr)) {
            $msg = array('status' => 3, 'info' => '杠牌非法，手牌数据有问题');
            $flag = $this->gameGangCard($serv, $fd, $msg);
        }

        if ($flag) {
            //本轮次上一次牌型
            $last_chair_id = isset($user_room_data['last_chair_id']) ? $user_room_data['last_chair_id'] : 0;
            $chair_id = $out_cards['chair_id']; // 座位号
            //下一个出牌人椅子id
            $next_chair_id = $chair_id;
            $my_card = $this->setMyCard($user_room_data, $card, $last_chair_id, $next_chair_id,
                $account);

            $room_no = json_decode($user_room_data['room_no'], true);
            //游戏进度：0.加入游戏阶段 1.准备阶段 2.换牌阶段 3.定缺阶段 4.出牌阶段 5.摸牌阶段 6.结算阶段
            $room_progress_key = sprintf($game_conf['user_room_progress'], $room_no);
            redis()->set($room_progress_key, 5);
            $fds = $this->getUsers($user_room_data['uinfo'], $game_conf);// 房间玩家链接
//            $this->gameGangCardResp($serv, $fds, $next_player);
            //全员发送通知，包含所杠牌的信息
            $user_room_info = Packet::packFormat('OK', 1, ['card' => $card,
                'chair_id' => $out_cards['chair_id'], 'next_chair_id' => $next_chair_id, 'wait_time' => $user_conf['play_timer']]);
            $return_data = Packet::packEncode($user_room_info, MainCmd::CMD_SYS,
                SubCmd::SUB_GAME_GANG_CARD_RESP);
            foreach ($fds as $fdv) {
                //获取客户端信息
                $client_info = $serv->getClientInfo($fdv);
                $client[$fdv] = $client_info;
                if (isset($client_info['websocket_status']) && $client_info['websocket_status'] == 3) {
                    $serv->push($fdv, $return_data, WEBSOCKET_OPCODE_BINARY);
                }
            }


//            $user_room_info = Packet::packFormat('OK', 1, ['card' => $card]);
//            $return_data = Packet::packEncode($user_room_info, MainCmd::CMD_SYS,
//                SubCmd::SUB_GAME_GANG_CARD_RESP);
//            $fds = $this->getUsers($user_room_data['uinfo'], $game_conf);// 房间玩家链接
//            foreach ($fds as $fdv) {
//                //获取客户端信息
//                $client_info = $serv->getClientInfo($fdv);
//                $client[$fdv] = $client_info;
//                if (isset($client_info['websocket_status']) && $client_info['websocket_status'] == 3) {
//                    $serv->push($fdv, $return_data, WEBSOCKET_OPCODE_BINARY);
//                }
//            }
        }

    }

    /**
     * 返回玩家房间桌位号
     * @param $room_no
     * @param $account
     * @return mixed
     */
    protected function findChairId($room_no, $account)
    {
        $game_conf = config('game');
        $room_chair_key = sprintf($game_conf['user_room_chair'], $room_no);
        $chair_data = json_decode(redis()->get($room_chair_key), true);
        return $chair_data[$account];
    }

    /**
     * 向客户端当前玩家发送错误提示响应, 单发
     * @param $serv
     * @param $fd
     * @param $param
     * @return bool
     */
    protected function gameGangCard($serv, $fd, $param)
    {
        $data = Packet::packFormat('OK', 0, $param);
        $data = Packet::packEncode($data, MainCmd::CMD_SYS, SubCmd::SUB_GAME_GANG_CARD_RESP);
        $serv->push($fd, $data, WEBSOCKET_OPCODE_BINARY);
        return false;
    }


    /**
     * 设置我的手牌
     * @param $user_room_data
     * @param $cards
     * @param $account
     * @return mixed
     */
    protected function setMyCard($user_room_data, $card, $last_chair_id, $next_chair_id, $account)
    {
        //根据椅子查询手牌信息
        $my_card = json_decode($user_room_data[$account], true);
        $my_card['card'][] = $card;
        $my_card['gang'][] = $card;
        sort($my_card['card']);
        $param[$account] = json_encode($my_card);
        $param['last_chair_id'] = $last_chair_id;
        $param['next_chair_id'] = $next_chair_id;
        //写会redis
        $this->updateRoomData($user_room_data['room_no'], $param);
        return $my_card;
    }


    /**
     * 批量更新房间数据
     * @param $room_no
     * @param $params
     */
    protected function updateRoomData($room_no, $params)
    {
        if (gettype($room_no) == 'string') {
            $room_no = json_decode($room_no, true);
        }
        $game_conf = config('game');
        $room_data_key = sprintf($game_conf['user_room_data'], $room_no);
        if (redis()->exists($room_data_key)) {
            foreach ($params as $key => $val) {
                redis()->hSet($room_data_key, (string)$key, $val);
            }
        }
    }


    /**
     * 向客户端广播下家出牌响应, 群发
     * @param $serv
     * @param $fds
     * @param $param
     */
    protected function gameGangCardResp($serv, $fds, $param)
    {
        $data = Packet::packFormat('OK', 1, $param);
        $data = Packet::packEncode($data, MainCmd::CMD_SYS, SubCmd::SUB_GAME_GANG_OVER_RESP);
        $this->pushToUsers($serv, $fds, $data);
    }

    /**
     * 对多用发送信息
     * @param $serv
     * @param $users
     * @param $data
     */
    protected function pushToUsers($serv, $users, $data)
    {
        foreach ($users as $fd) {
            //获取客户端信息
            $client_info = $serv->getClientInfo($fd);
            $client[$fd] = $client_info;
            if (isset($client_info['websocket_status']) && $client_info['websocket_status'] == 3) {
                $serv->push($fd, $data, WEBSOCKET_OPCODE_BINARY);
            }
        }
    }

    /**
     * 取出房间所有用户
     * @param $user_info
     * @param $game_conf
     * @return array
     */
    protected function getUsers($user_info, $game_conf)
    {
        $users = [];
        $uinfo = json_decode($user_info, true);
        if (gettype($uinfo) == 'string') {
            $uinfo = json_decode($uinfo, true);
        }
        dd('uinfo', $uinfo);
        foreach ($uinfo as $k => $v) {
            $user_bind_key = sprintf($game_conf['user_bind_key'], $k);
            $users[] = redis()->get($user_bind_key);
        }
        return $users;
    }

}